package com.android.support.lib.universal.view.tv;

import android.animation.Animator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;

import com.android.support.lib.universal.view.tv.bridge.EffectNoDrawBridge;
import com.android.support.lib.universal.view.tv.bridge.OpenEffectBridge;
import com.android.support.lib.universal.view.tv.bridge.WidgetTvViewBring;


/**
 * GridView TV升级版本.(基本解决了焦点错乱的问题)
 * 一：实例化
 * 二：添加事件 gridViewTV.setOnEnterUp();
 * 三：在Activity中dispatchKeyEvent方法中，监听按键值：GridViewTV.keyCode=event.getKeyCode();
 */
public class GridViewTV extends GridView {
    private ENTERUP enterup;//判断确认件或中间件是否按下

    public interface ENTERUP {//按键点击事件接口

        public void onKeyUP();
    }

    private MainUpView mainUpView;//效果框
    private float scale = 1.1f;//聚焦时的放到倍率,MainUpView
    private float mainUpViewPadding = 0;//效果框的内补丁
    private static View mOldFocus; // 4.3以下版本需要自己保存.

    public void setScale(float scale) {
        this.scale = scale;
    }

    //grideview在首次聚焦之后，可能会调用一次OnItemSelected()方法。
    private boolean BHasFocuse;//判断gridview是否首次聚焦。
    private int firstPosition;//首次聚焦时的下标选择。

    public static int keyCode;//按键值,在Activity中dispatchKeyEvent方法中，监听按键值。如：GridViewTV.keyCode=event.getKeyCode();

    public GridViewTV(Context context) {
        super(context);
        init(context, null);
    }

    public GridViewTV(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        try {
            super.dispatchDraw(canvas);
        } catch (Exception e) {
            Log.e("test", "GridViewTV崩溃了:\t" + e.getMessage());
            e.printStackTrace();
        }
    }

    WidgetTvViewBring mWidgetTvViewBring;

    private void init(Context context, AttributeSet attrs) {
        this.setChildrenDrawingOrderEnabled(true);
        mWidgetTvViewBring = new WidgetTvViewBring(this);
    }

    @Override
    public void bringChildToFront(View child) {
        mWidgetTvViewBring.bringChildToFront(this, child);
    }

    @Override
    protected int getChildDrawingOrder(int childCount, int i) {
        return mWidgetTvViewBring.getChildDrawingOrder(childCount, i);
    }

    Boolean BENTER = false;

    //遥控器触发按键事件，不会触发鼠标点击事件(属于触摸事件)。
    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            BENTER = false;
            switch (event.getKeyCode()) {
                case KeyEvent.KEYCODE_DPAD_CENTER://中间
                case KeyEvent.KEYCODE_ENTER://确认
                    BENTER = true;
                    break;
            }
        }
        return super.dispatchKeyEvent(event);

    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (BENTER && enterup != null) {
            handler.sendEmptyMessageDelayed(1, 50);//通过线程恢复BENTER = false;防止重复调用点击事件
            enterup.onKeyUP();
        }
        if (BHasFocuse) {
            BHasFocuse=false;
        }
        return super.onKeyUp(keyCode, event);
    }

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            removeMessages(msg.what);//防止线程错乱，必须清除。
            switch (msg.what) {
                case 0:
                    setFocusable(true);//为防止程序奔溃，要及时恢复焦点。
                    setFocusableInTouchMode(true);//设置为可触控,防止鼠标点击没有效果。
                    break;
                case 1:
                    BENTER = false;//切记。要恢复成false,否则麻烦很大。
                    break;
            }


        }
    };

    /**
     * 确认键手指离开监听。因为TV端遥控器无法触发触摸(或鼠标点击事件),所以在此用接口监听。
     *
     * @param enterup           GridViewTV.ENTERUP按键离开监听接口
     * @param mainUpView        效果框，可为null
     * @param mainUpViewPadding 效果框，内补丁。
     */
    public void setOnEnterUp(ENTERUP enterup, MainUpView mainUpView, float mainUpViewPadding) {
        this.enterup = enterup;
        if (mainUpView != null) {
            this.mainUpView = mainUpView;
            this.mainUpViewPadding = mainUpViewPadding;
            setSelector(new ColorDrawable(Color.TRANSPARENT));
            OnFocusChange();
            OnItemSelected();
            OnItemClick();

            //防止垮屏时，自动聚焦。放心item仍然能够正常聚焦。
            //初始化时，这样不行。程序有时会奔溃。
            setFocusable(false);
            handler.sendEmptyMessageDelayed(0, 50);
        }

    }

    //根据当前按键值进行聚焦(主要针对左右按键)。
    private void OnFouceKey() {
        int position = getSelectedItemPosition();
        if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
            int select = position / getNumColumns();
            float fSelect = (float) position / (float) getNumColumns();
            if (select != fSelect) {
                firstPosition = 0;
                setSelection(0);
            }

        }
        if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
            int count = getCount();

            if (position < count - 1) {
                int select = (getSelectedItemPosition() + 1) / getNumColumns();
                float fSelect = ((float) getSelectedItemPosition() + 1) / (float) getNumColumns();
                if (select != fSelect) {
                    if (count <= getNumColumns()) {
                        firstPosition = count - 1;
                        setSelection(count - 1);
                    } else {
                        firstPosition = getNumColumns() - 1;
                        setSelection(getNumColumns() - 1);
                    }

                }
            }

        }
    }

    //GridViewTv首次聚焦时的变化,view首次聚焦时是无法捕捉按下键的。因为当时还没聚焦
    private void OnFocusChange() {
        setOnFocusChangeListener(new OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if (hasFocus) {
                    OnFouceKey();
                    View view = getSelectedView();
                    if (view != getChildAt(getSelectedItemPosition())) {
                        view = getChildAt(getSelectedItemPosition());
                    }
                    if (view == null) {
                        view = getChildAt(0);
                    }
                    if (view != null) {
                        mOldFocus = null;
                        mainUpView.setDrawUpRectPadding(new RectF(mainUpViewPadding, 0, mainUpViewPadding, 0));
                        mainUpView.setFocusView(view, scale);
                        mOldFocus = view;
                        ((EffectNoDrawBridge) mainUpView.getEffectBridge()).setOnAnimatorListener(null);
                    }
                } else {
                    if (mOldFocus != null) {
                        ((EffectNoDrawBridge) mainUpView.getEffectBridge()).setOnAnimatorListener(new OpenEffectBridge.NewAnimatorListener() {
                            @Override
                            public void onAnimationStart(OpenEffectBridge bridge, View view, Animator animation) {
                            }

                            @Override
                            public void onAnimationEnd(OpenEffectBridge bridge, View view, Animator animation) {
                                mainUpView.setVisibility(View.GONE);//防止因为动画，mianupView未能隐藏
                            }
                        });
                        mainUpView.setUnFocusView(mOldFocus);
                        mainUpView.setVisibility(View.GONE);
                    }
                }
                BHasFocuse = hasFocus;
                firstPosition = getSelectedItemPosition();
            }
        });
    }

    //item选中时的聚焦变化
    private void OnItemSelected() {
        setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                if (BHasFocuse) {
                    BHasFocuse = false;
                    setSelection(firstPosition);
                } else if (isFocused()) {//GridView本身要聚焦
                    if (view != null && mOldFocus != view) {//两个不能相同，否则会出现边框和图片一大一小的情况
                        mainUpView.setFocusView(view, scale);
                    } else if (mOldFocus != null) {
                        mainUpView.setFocusView(view, scale);
                    }
                    mOldFocus = view;
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });
    }

    //防止item鼠标点击时不能聚焦
    private void OnItemClick() {
        setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
                setFocusable(true);//设置聚焦能力
                requestFocus();//聚焦，在触摸时(或鼠标点击)不能聚焦。
                requestFocusFromTouch();//聚焦，在触摸时(或鼠标点击)也能聚焦
                //只有当前Gridview本身聚焦，才有效果。
                setSelection(position);
                firstPosition = getSelectedItemPosition();
                BHasFocuse = false;
                if (enterup != null && !BENTER) {//!BENTER防止重复调用
                    //鼠标点击时也能触发事件
                    enterup.onKeyUP();
                }
            }
        });
    }

}
